package com.hj.util;

import android.content.ContentResolver;
import android.database.Cursor;
import android.net.Uri;
import android.os.Handler;
import android.os.Looper;
import android.provider.MediaStore;
import android.text.TextUtils;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class LoadPictureThread extends Thread {
//    uri:用于检索内容的 URI
//    projection :返回的列的列表。传递 null 时，将返回所有列，这样的话效率会很低
//    selection :一种用于声明返回那些行的过滤器，采用 SQL WHERE 子句格式。传递 null 时，将为指定的 URI 返回所有行
//    selectionArgs:我们可以在 selection 中包含 ?，它将按照在 selection 中显示的顺序替换为 selectionArgs 中的值
//    sortOrder:行的排序依据，采用 SQL ORDER BY 子句格式。传递 null 时，将使用默认排序顺序（可能并未排序）

//    图片信息:images
//    _id:  	主键。图片 id，从 1 开始自增
//    _data:	图片绝对路径
//    _size:	文件大小，单位为 byte
//    _display_name:	文件名
//    mime_type:	类似于 image/jpeg 的 MIME 类型
//    title:	不带扩展名的文件名
//    date_added:	添加到数据库的时间，单位秒
//    date_modified:	文件最后修改时间，单位秒
//    description:
//    picasa_id:	用于 picasa 网络相册
//    isprivate:
//    latitude: 	纬度，需要照片有 GPS 信息
//    longitude:	经度，需要照片有 GPS 信息
//    datetaken:	取自 EXIF 照片拍摄时间，若为空则等于文件修改时间，单位毫秒
//    orientation:  	取自 EXIF 旋转角度，在图库旋转图片也会改变此值
//    mini_thumb_magic: 	取小缩略图时生成的一个随机数，见 MediaThumbRequest
//    bucket_id:	等于 path.toLowerCase.hashCode()，见 MediaProvider.computeBucketValues()
//    bucket_display_name:  	直接包含图片的文件夹就是该图片的 bucket，就是文件夹名

//    缩略图信息:thumbnails
//    _id:  	主键。缩略图 id，从 1 开始自增
//    _data:	图片绝对路径
//    image_id: 	缩略图所对应图片的 id，依赖于 images 表 _id 字段，可建立外键
//    kind: 	缩略图类型，1 是大缩略图，2 基本不用，3 是微型缩略图但其信息不保存在数据库
//    width:	缩略图宽度
//    height:   	缩略图高度

    public static final Uri QUERY_URI = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
    public static final String[] PROJECTION = new String[]{
            MediaStore.Images.ImageColumns._ID,
            MediaStore.Images.ImageColumns.BUCKET_ID,
            MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME,
            MediaStore.Images.ImageColumns.DISPLAY_NAME,
            MediaStore.Images.ImageColumns.SIZE,
            MediaStore.Images.ImageColumns.DATA,
            MediaStore.Images.ImageColumns.MIME_TYPE,
            MediaStore.Images.ImageColumns.TITLE,
            MediaStore.Images.ImageColumns.DATE_ADDED,
            MediaStore.Images.ImageColumns.DATE_MODIFIED,
            MediaStore.Images.ImageColumns.LATITUDE,
            MediaStore.Images.ImageColumns.LONGITUDE,
            MediaStore.Images.ImageColumns.DATE_TAKEN,
            MediaStore.Images.ImageColumns.WIDTH,
            MediaStore.Images.ImageColumns.HEIGHT
    };
    public static final String SORTORDER = MediaStore.Images.Media.DATE_TAKEN + " DESC";

    public static final String SELECTION = MediaStore.Images.ImageColumns.SIZE + ">0 AND " + MediaStore.Images.Media.MIME_TYPE + "=? or " +
            MediaStore.Images.Media.MIME_TYPE + "=? or " +
            MediaStore.Images.Media.MIME_TYPE + "=?";
    public static final String[] SELECTIONARGS = new String[]{"image/jpeg", "image/png", "image/jpg"};

    private Handler mainHandler = new Handler(Looper.getMainLooper());
    private ContentResolver resolver;
    private boolean loading = false;
    private List<PicturesObject> list = new ArrayList<>();
    private Callback callback;

    public LoadPictureThread(ContentResolver resolver, Callback callback) {
        this.resolver = resolver;
        this.callback = callback;
    }

    public boolean isLoading() {
        return loading;
    }

    public PicturesObject getPicturesObject(int id, String name) {
        for (PicturesObject obj :
                list) {
            if (obj.equals(id, name)) {
                return obj;
            }
        }
        return null;
    }

    public void cancel() {
        loading = false;
        this.callback = null;
//        if (!interrupted())
//            interrupt();
    }

    @Override
    public void run() {
        if (resolver != null) {
            loading = true;
            Cursor cursor = null;
            try {
                cursor = resolver.query(QUERY_URI, PROJECTION, SELECTION, SELECTIONARGS, SORTORDER);
                if (cursor != null && loading) {
                    while (cursor.moveToNext()) {
                        if (!loading) {
                            //提前主动取消结束
                            break;
                        }
                        int id = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns._ID));
                        int pictureId = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.BUCKET_ID));
                        String pictureName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.BUCKET_DISPLAY_NAME));
                        String name = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME));
                        long size = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.ImageColumns.SIZE));
                        String data = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA));
                        String mimeType = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.MIME_TYPE));
                        String title = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.TITLE));
                        long dateAdded = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_ADDED));
                        long dateModified = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_MODIFIED));
                        double latitude = cursor.getDouble(cursor.getColumnIndex(MediaStore.Images.ImageColumns.LATITUDE));
                        double longitude = cursor.getDouble(cursor.getColumnIndex(MediaStore.Images.ImageColumns.LONGITUDE));
                        long dateTaken = cursor.getLong(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATE_TAKEN));
                        int width = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.WIDTH));
                        int height = cursor.getInt(cursor.getColumnIndex(MediaStore.Images.ImageColumns.HEIGHT));

                        PicturesObject picture = getPicturesObject(pictureId, pictureName);
                        if (picture == null) {
                            picture = new PicturesObject();
                            picture.setId(pictureId);
                            picture.setName(pictureName);
                            picture.setIcon(data);
                            list.add(picture);
                        }
                        PicturesObject.Image image = new PicturesObject.Image();
                        image.setId(id);
                        image.setName(name);
                        image.setData(data);
                        image.setSize(size);
                        image.setMimeType(mimeType);
                        image.setTitle(title);
                        image.setDateAdded(dateAdded);
                        image.setDateModified(dateModified);
                        image.setLatitude(latitude);
                        image.setLongitude(longitude);
                        image.setDatetaken(dateTaken);
                        image.setWidth(width);
                        image.setHeight(height);

                        picture.AddImage(image);
                    }
                }
            } catch (Exception e) {
                System.out.println("load picture exception.");
            } finally {
                if (cursor != null) {
                    cursor.close();
                }
                cursor = null;
                mainHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (callback != null) {
                            callback.onResult(list);
                        }
                        callback = null;
                        resolver = null;
                        loading = false;
                        list.clear();
                        list = null;
                    }
                });
            }
        }
    }

    public interface Callback {
        void onResult(List<PicturesObject> list);
    }

    public static class PicturesObject implements Serializable {
        private static final long serialVersionUID = 5115308589610403098L;
        private int id;
        private String name;
        private String icon;
        private List<Image> images;

        public PicturesObject() {
            this.name = "";
            this.icon = "";
        }

        public PicturesObject(int id, String name, String icon) {
            this.id = id;
            this.name = name;
            this.icon = icon;
        }

        public PicturesObject(int id, String name, String icon, List<Image> images) {
            this.id = id;
            this.name = name;
            this.icon = icon;
            this.images = images;
        }

        public int getId() {
            return id;
        }

        public void setId(int id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public String getIcon() {
            return icon;
        }

        public void setIcon(String icon) {
            this.icon = icon;
        }

        public List<Image> getImages() {
            return images;
        }

        public void setImages(List<Image> images) {
            this.images = images;
        }

        public synchronized void AddImage(Image image) {
            if (image != null) {
                if (this.images == null) {
                    this.images = new ArrayList<>();
                }
                for (Image obj :
                        this.images) {
                    if (obj.equals(image)) {
                        return;
                    }
                }
                this.images.add(image);
            }
        }

        public boolean equals(int id, String name) {
            return (this.id == id && ((TextUtils.isEmpty(this.name) && TextUtils.isEmpty(name)) || (!TextUtils.isEmpty(this.name) && this.name.equals(name))));
        }

        @Override
        public String toString() {
            return "PicturesObject={\nid:" + this.id
                    + "\nname:" + this.name
                    + "\nicon:" + this.icon
                    + "\nimages:" + Arrays.toString(images.toArray())
                    + "}";
        }

        public static class Image implements Serializable {
            private static final long serialVersionUID = -720529944421320271L;
            private int id;//图片 id
            private String name;//文件名
            private long size;//文件大小，单位为 byte
            private String data;//图片绝对路径
            private String mimeType;//类似于 image/jpeg 的 MIME 类型
            private String title;//不带扩展名的文件名
            private long dateAdded;//添加到数据库的时间，单位秒
            private long dateModified;//文件最后修改时间，单位秒
            private double latitude;//纬度，需要照片有 GPS 信息
            private double longitude;//经度，需要照片有 GPS 信息
            private long datetaken;//取自 EXIF 照片拍摄时间，若为空则等于文件修改时间，单位毫秒
            private int orientation;//取自 EXIF 旋转角度，在图库旋转图片也会改变此值
            private int width;
            private int height;
            private boolean check;//预留选择标志

            public Image() {
            }

            public int getId() {
                return id;
            }

            public void setId(int id) {
                this.id = id;
            }

            public String getName() {
                return name;
            }

            public void setName(String name) {
                this.name = name;
            }

            public long getSize() {
                return size;
            }

            public void setSize(long size) {
                this.size = size;
            }

            public String getData() {
                return data;
            }

            public void setData(String data) {
                this.data = data;
            }

            public String getMimeType() {
                return mimeType;
            }

            public void setMimeType(String mimeType) {
                this.mimeType = mimeType;
            }

            public String getTitle() {
                return title;
            }

            public void setTitle(String title) {
                this.title = title;
            }

            public long getDateAdded() {
                return dateAdded;
            }

            public void setDateAdded(long dateAdded) {
                this.dateAdded = dateAdded;
            }

            public long getDateModified() {
                return dateModified;
            }

            public void setDateModified(long dateModified) {
                this.dateModified = dateModified;
            }

            public double getLatitude() {
                return latitude;
            }

            public void setLatitude(double latitude) {
                this.latitude = latitude;
            }

            public double getLongitude() {
                return longitude;
            }

            public void setLongitude(double longitude) {
                this.longitude = longitude;
            }

            public long getDatetaken() {
                return datetaken;
            }

            public void setDatetaken(long datetaken) {
                this.datetaken = datetaken;
            }

            public int getOrientation() {
                return orientation;
            }

            public void setOrientation(int orientation) {
                this.orientation = orientation;
            }

            public int getWidth() {
                return width;
            }

            public void setWidth(int width) {
                this.width = width;
            }

            public int getHeight() {
                return height;
            }

            public void setHeight(int height) {
                this.height = height;
            }

            public boolean isCheck() {
                return check;
            }

            public void setCheck(boolean check) {
                this.check = check;
            }

            public boolean equals(int id) {
                return this.id == id;
            }

            public boolean equals(Image obj) {
                return obj == null ? false : this.id == obj.id;
            }

            @Override
            public String toString() {
                return "Image={"
                        + "\nid:" + this.id
                        + "\nname:" + this.name
                        + "\nsize:" + this.size
                        + "\ndata:" + this.data
                        + "\nmimeType:" + this.mimeType
                        + "\ntitle:" + this.title
                        + "\ndateAdded:" + this.dateAdded
                        + "\ndateModified:" + this.dateModified
                        + "\nlatitude:" + this.latitude
                        + "\nlongitude:" + this.longitude
                        + "\ndatetaken:" + this.datetaken
                        + "\norientation:" + this.orientation
                        + "\nwidth:" + this.width
                        + "\nheight:" + this.height
                        + "}";
            }
        }
    }
}
